package com.rickpan.controller;

import com.rickpan.common.ApiResponse;
import com.rickpan.entity.ProjectAnnouncement;
import com.rickpan.service.ProjectAnnouncementService;
import com.rickpan.utils.SecurityUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.*;

import jakarta.validation.Valid;
import java.time.LocalDateTime;
import java.util.List;

/**
 * 项目公告管理控制器
 * 
 * @author RickPan Team
 * @since 2024-01-15
 */
@RestController
@RequestMapping("/api/announcements")
@Tag(name = "项目公告管理", description = "项目公告管理相关接口")
public class ProjectAnnouncementController {

    private static final Logger logger = LoggerFactory.getLogger(ProjectAnnouncementController.class);

    @Autowired
    private ProjectAnnouncementService announcementService;

    /**
     * 创建公告
     */
    @PostMapping
    @Operation(summary = "创建公告", description = "在项目中创建新公告")
    public ApiResponse<ProjectAnnouncement> createAnnouncement(@Valid @RequestBody CreateAnnouncementRequest request) {
        logger.info("创建公告请求: {}", request.getTitle());

        Long userId = SecurityUtils.getCurrentUserId();
        
        // 创建公告实体
        ProjectAnnouncement announcement = new ProjectAnnouncement();
        announcement.setProjectId(request.getProjectId());
        announcement.setTitle(request.getTitle());
        announcement.setContent(request.getContent());
        announcement.setCreatorId(userId);
        announcement.setIsPinned(request.getIsPinned());
        
        ProjectAnnouncement createdAnnouncement = announcementService.createAnnouncement(announcement);
        return ApiResponse.success("公告创建成功", createdAnnouncement);
    }

    /**
     * 更新公告
     */
    @PutMapping("/{announcementId}")
    @Operation(summary = "更新公告", description = "更新公告信息")
    public ApiResponse<ProjectAnnouncement> updateAnnouncement(
            @Parameter(description = "公告ID") @PathVariable Long announcementId,
            @Valid @RequestBody UpdateAnnouncementRequest request) {
        logger.info("更新公告请求: {}", announcementId);

        Long userId = SecurityUtils.getCurrentUserId();
        
        // 检查权限
        if (!announcementService.hasAnnouncementManagePermission(announcementId, userId)) {
            return ApiResponse.error("无权限管理此公告");
        }
        
        // 更新公告实体
        ProjectAnnouncement announcement = announcementService.findById(announcementId)
                .orElseThrow(() -> new RuntimeException("公告不存在"));
        
        announcement.setTitle(request.getTitle());
        announcement.setContent(request.getContent());
        announcement.setIsPinned(request.getIsPinned());
        
        ProjectAnnouncement updatedAnnouncement = announcementService.updateAnnouncement(announcement);
        return ApiResponse.success("公告更新成功", updatedAnnouncement);
    }

    /**
     * 删除公告
     */
    @DeleteMapping("/{announcementId}")
    @Operation(summary = "删除公告", description = "删除指定公告")
    public ApiResponse<Void> deleteAnnouncement(
            @Parameter(description = "公告ID") @PathVariable Long announcementId) {
        logger.info("删除公告请求: {}", announcementId);

        Long userId = SecurityUtils.getCurrentUserId();
        
        // 检查权限
        if (!announcementService.hasAnnouncementManagePermission(announcementId, userId)) {
            return ApiResponse.error("无权限管理此公告");
        }
        
        announcementService.deleteAnnouncement(announcementId);
        return ApiResponse.success("公告删除成功");
    }

    /**
     * 获取公告详情
     */
    @GetMapping("/{announcementId}")
    @Operation(summary = "获取公告详情", description = "根据ID获取公告详细信息")
    public ApiResponse<ProjectAnnouncement> getAnnouncement(
            @Parameter(description = "公告ID") @PathVariable Long announcementId) {
        logger.info("获取公告详情: {}", announcementId);

        Long userId = SecurityUtils.getCurrentUserId();
        
        // 检查权限
        if (!announcementService.hasAnnouncementViewPermission(announcementId, userId)) {
            return ApiResponse.error("无权限查看此公告");
        }
        
        ProjectAnnouncement announcement = announcementService.findById(announcementId)
                .orElseThrow(() -> new RuntimeException("公告不存在"));
        
        return ApiResponse.success("获取成功", announcement);
    }

    /**
     * 获取项目公告列表
     */
    @GetMapping("/project/{projectId}")
    @Operation(summary = "获取项目公告列表", description = "获取指定项目的所有公告")
    public ApiResponse<List<ProjectAnnouncement>> getProjectAnnouncements(
            @Parameter(description = "项目ID") @PathVariable Long projectId,
            @Parameter(description = "是否只获取置顶公告") @RequestParam(required = false) Boolean pinned) {
        logger.info("获取项目公告列表: {}", projectId);

        List<ProjectAnnouncement> announcements;
        if (pinned != null) {
            if (pinned) {
                announcements = announcementService.findPinnedAnnouncementsByProject(projectId);
            } else {
                announcements = announcementService.findNormalAnnouncementsByProject(projectId);
            }
        } else {
            announcements = announcementService.findAnnouncementsByProject(projectId);
        }
        
        return ApiResponse.success("获取成功", announcements);
    }

    /**
     * 分页获取项目公告列表
     */
    @GetMapping("/project/{projectId}/page")
    @Operation(summary = "分页获取项目公告列表", description = "分页获取指定项目的公告")
    public ApiResponse<Page<ProjectAnnouncement>> getProjectAnnouncementsPage(
            @Parameter(description = "项目ID") @PathVariable Long projectId,
            @Parameter(description = "页码") @RequestParam(defaultValue = "0") int page,
            @Parameter(description = "页大小") @RequestParam(defaultValue = "10") int size,
            @Parameter(description = "是否只获取非置顶公告") @RequestParam(required = false) Boolean excludePinned) {
        logger.info("分页获取项目公告列表: {}, page: {}, size: {}", projectId, page, size);

        Pageable pageable = PageRequest.of(page, size);
        Page<ProjectAnnouncement> announcements;
        
        if (excludePinned != null && excludePinned) {
            announcements = announcementService.findNormalAnnouncementsByProject(projectId, pageable);
        } else {
            announcements = announcementService.findAnnouncementsByProject(projectId, pageable);
        }
        
        return ApiResponse.success("获取成功", announcements);
    }

    /**
     * 搜索公告
     */
    @GetMapping("/project/{projectId}/search")
    @Operation(summary = "搜索公告", description = "在项目中搜索公告")
    public ApiResponse<List<ProjectAnnouncement>> searchAnnouncements(
            @Parameter(description = "项目ID") @PathVariable Long projectId,
            @Parameter(description = "搜索关键词") @RequestParam String keyword) {
        logger.info("搜索公告: {}, 关键词: {}", projectId, keyword);

        List<ProjectAnnouncement> announcements = announcementService.searchAnnouncements(projectId, keyword);
        return ApiResponse.success("搜索成功", announcements);
    }

    /**
     * 根据日期范围查询公告
     */
    @GetMapping("/project/{projectId}/date-range")
    @Operation(summary = "根据日期范围查询公告", description = "查询指定日期范围内的公告")
    public ApiResponse<List<ProjectAnnouncement>> getAnnouncementsByDateRange(
            @Parameter(description = "项目ID") @PathVariable Long projectId,
            @Parameter(description = "开始日期") @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime startDate,
            @Parameter(description = "结束日期") @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime endDate) {
        logger.info("根据日期范围查询公告: {}, 开始: {}, 结束: {}", projectId, startDate, endDate);

        List<ProjectAnnouncement> announcements = announcementService.findAnnouncementsByDateRange(projectId, startDate, endDate);
        return ApiResponse.success("查询成功", announcements);
    }

    /**
     * 获取今日公告
     */
    @GetMapping("/project/{projectId}/today")
    @Operation(summary = "获取今日公告", description = "获取今天发布的公告")
    public ApiResponse<List<ProjectAnnouncement>> getTodayAnnouncements(
            @Parameter(description = "项目ID") @PathVariable Long projectId) {
        logger.info("获取今日公告: {}", projectId);

        List<ProjectAnnouncement> announcements = announcementService.findTodayAnnouncements(projectId);
        return ApiResponse.success("获取成功", announcements);
    }

    /**
     * 获取本周公告
     */
    @GetMapping("/project/{projectId}/week")
    @Operation(summary = "获取本周公告", description = "获取本周发布的公告")
    public ApiResponse<List<ProjectAnnouncement>> getWeekAnnouncements(
            @Parameter(description = "项目ID") @PathVariable Long projectId) {
        logger.info("获取本周公告: {}", projectId);

        List<ProjectAnnouncement> announcements = announcementService.findWeekAnnouncements(projectId);
        return ApiResponse.success("获取成功", announcements);
    }

    /**
     * 获取本月公告
     */
    @GetMapping("/project/{projectId}/month")
    @Operation(summary = "获取本月公告", description = "获取本月发布的公告")
    public ApiResponse<List<ProjectAnnouncement>> getMonthAnnouncements(
            @Parameter(description = "项目ID") @PathVariable Long projectId) {
        logger.info("获取本月公告: {}", projectId);

        List<ProjectAnnouncement> announcements = announcementService.findMonthAnnouncements(projectId);
        return ApiResponse.success("获取成功", announcements);
    }

    /**
     * 置顶公告
     */
    @PutMapping("/{announcementId}/pin")
    @Operation(summary = "置顶公告", description = "将公告置顶")
    public ApiResponse<Void> pinAnnouncement(
            @Parameter(description = "公告ID") @PathVariable Long announcementId) {
        logger.info("置顶公告: {}", announcementId);

        Long userId = SecurityUtils.getCurrentUserId();
        
        // 检查权限
        if (!announcementService.hasAnnouncementManagePermission(announcementId, userId)) {
            return ApiResponse.error("无权限管理此公告");
        }
        
        announcementService.pinAnnouncement(announcementId);
        return ApiResponse.success("公告已置顶");
    }

    /**
     * 取消置顶公告
     */
    @PutMapping("/{announcementId}/unpin")
    @Operation(summary = "取消置顶公告", description = "取消公告置顶")
    public ApiResponse<Void> unpinAnnouncement(
            @Parameter(description = "公告ID") @PathVariable Long announcementId) {
        logger.info("取消置顶公告: {}", announcementId);

        Long userId = SecurityUtils.getCurrentUserId();
        
        // 检查权限
        if (!announcementService.hasAnnouncementManagePermission(announcementId, userId)) {
            return ApiResponse.error("无权限管理此公告");
        }
        
        announcementService.unpinAnnouncement(announcementId);
        return ApiResponse.success("已取消公告置顶");
    }

    /**
     * 获取公告统计信息
     */
    @GetMapping("/project/{projectId}/statistics")
    @Operation(summary = "获取公告统计信息", description = "获取项目的公告统计数据")
    public ApiResponse<ProjectAnnouncementService.AnnouncementStatistics> getAnnouncementStatistics(
            @Parameter(description = "项目ID") @PathVariable Long projectId) {
        logger.info("获取公告统计信息: {}", projectId);

        ProjectAnnouncementService.AnnouncementStatistics statistics = announcementService.getAnnouncementStatistics(projectId);
        return ApiResponse.success("获取成功", statistics);
    }

    /**
     * 创建公告请求DTO
     */
    public static class CreateAnnouncementRequest {
        private Long projectId;
        private String title;
        private String content;
        private Boolean isPinned;

        // Getter 和 Setter
        public Long getProjectId() { return projectId; }
        public void setProjectId(Long projectId) { this.projectId = projectId; }

        public String getTitle() { return title; }
        public void setTitle(String title) { this.title = title; }

        public String getContent() { return content; }
        public void setContent(String content) { this.content = content; }

        public Boolean getIsPinned() { return isPinned; }
        public void setIsPinned(Boolean isPinned) { this.isPinned = isPinned; }
    }

    /**
     * 更新公告请求DTO
     */
    public static class UpdateAnnouncementRequest {
        private String title;
        private String content;
        private Boolean isPinned;

        // Getter 和 Setter
        public String getTitle() { return title; }
        public void setTitle(String title) { this.title = title; }

        public String getContent() { return content; }
        public void setContent(String content) { this.content = content; }

        public Boolean getIsPinned() { return isPinned; }
        public void setIsPinned(Boolean isPinned) { this.isPinned = isPinned; }
    }
}
